package cn.tedu.lucky.draw.server.aspect;

import cn.tedu.lucky.draw.server.common.annotation.OperationLog;
import cn.tedu.lucky.draw.server.protocol.po.UserLog;
import cn.tedu.lucky.draw.server.repository.UserLogRepository;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Component
public class LogAspect {

    @Autowired
    private UserLogRepository userLogRepository;

    @Pointcut("@annotation(cn.tedu.lucky.draw.server.common.annotation.OperationLog)")
    public void doLog(){}

    @Around("doLog()")
    public Object doLogAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 初始状态
        int status =1;
        // 错误信息
        String error=null;
        long time=0l;
        //开始执行日志处理
        long t1=System.currentTimeMillis();
        try{
            //调用目标方法
            Object result=joinPoint.proceed();
            long t2=System.currentTimeMillis();
            time=t2-t1;
            return result;
        }catch (Throwable e){
            long t3=System.currentTimeMillis();
            time=t3-t1;
            status=0;
            error=e.getMessage();
            throw e;
        }finally {
            saveOperationLog(joinPoint,status,error,time);
        }
    }

    private void saveOperationLog(ProceedingJoinPoint joinPoint, int status, String error, long time) throws NoSuchMethodException, JsonProcessingException {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        //获取IP地址
        String ip = request.getRemoteAddr();
        //获取用户名
        String username="tedu";
        Class<?> targetCls = joinPoint.getTarget().getClass();
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method targetMethod = targetCls.getDeclaredMethod(ms.getName(), ms.getParameterTypes());
        OperationLog operationLog = targetMethod.getAnnotation(OperationLog.class);
        //获取操作描述
        String operation = operationLog.operation();
        //获取方法名称
        String method =targetCls.getName()+"."+targetMethod.getName();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModule(new JavaTimeModule());
        String params = objectMapper.writeValueAsString(joinPoint.getArgs());
        UserLog userLog = new UserLog();
        userLog.setUsername(username);
        userLog.setIp(ip);
        userLog.setOperation(operation);
        userLog.setMethod(method);
        userLog.setParams(params);
        userLog.setStatus(status);
        userLog.setError(error);
        userLog.setCreateTime(LocalDateTime.now());
        userLog.setTime(time);
        userLogRepository.save(userLog);

    }
}
